package com.instalinks.android.smspostservice.utils;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Date;
import java.util.Hashtable;

import android.app.ActivityManager;
import android.app.ActivityManager.RunningServiceInfo;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;

import com.instalinks.android.lib.AppHelper;
import com.instalinks.android.lib.Config;
import com.instalinks.android.lib.NotificationQueue;
import com.instalinks.android.lib.PhoneAttributes;
import com.instalinks.android.lib.UrlData;
import com.instalinks.android.lib.UrlResponse;
import com.instalinks.android.lib.UrlResponse.UrlResponseType;
import com.instalinks.android.lib.enums.DeviceType;
import com.instalinks.android.lib.enums.NetworkType;
import com.instalinks.android.smspostservice.R;
import com.instalinks.android.smspostservice.service.AppService;
import com.instalinks.android.smspostservice.utils.enums.ConfigParams;
import com.instalinks.android.smspostservice.utils.enums.PhoneParams;
import com.instalinks.android.smspostservice.utils.enums.ServiceStartStatus;
import com.instalinks.android.smspostservice.utils.enums.ServiceTypes;

public class AppConfig extends Config {

	private PhoneAttributes mPhoneAttr;
	private NotificationQueue mNotificationQueue;

	public AppConfig(Context context) {
		super(context, Constants.CONFIG_FILE_NAME, false);

		mNotificationQueue = new NotificationQueue(context,
				Constants.NOTIFICATION_FILE_NAME, 20);
		this.rePopulate();
	}

	
	public String getAppUrl() throws Exception{
		try {
			UrlData urlData = new UrlData(Constants.APP_CONFIG_URL, 25000);

			Hashtable<String, String> htParams = new Hashtable<String, String>();

			htParams.put(ConfigParams.appid.toString(), this.mContext.getPackageName());

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				String url = response.getMessage();
				url = url.replace("\n", "");
				try{
					this.setDataPostUrl(url);
				}catch(Exception e){
				}
				return url;//response.getMessage();
			} else {
				throw new Exception("Error getting application data post url. Try reopening the application");
			}
		} catch (Exception e) {
			throw e;
		}
	}
	
	
	public boolean isAppUpToDate() {
		return true;
	}

	public void registerForC2dm() {

		if (this.isConfigExists()) {
			if (this.getRegistrationId() == null
					|| this.getRegistrationId().trim().length() < 10) {

				AppHelper.registerForC2dm(mContext, Constants.C2DM_EMAIL);
			}
		}
	}

	public void unregisterForC2dm() {

		AppHelper.unregisterForC2dm(mContext);
	}
	
	public Hashtable<String, String> getDataPostHashtable(){
		Hashtable<String, String> htParams = new Hashtable<String, String>();

		htParams.put(ConfigParams.scode.toString(), getScode());
		htParams.put(PhoneParams.subid.toString(), getSubscriberId());
		htParams.put(PhoneParams.deviceid.toString(), getDeviceId());
		htParams.put(PhoneParams.email.toString(), getEmail());
		
		return htParams;
	}

	public boolean activateDevice() {
		try {
			UrlData urlData = new UrlData(this.getDataPostUrl(), 25000);

			Hashtable<String, String> htParams = getDataPostHashtable();

			htParams.put(ConfigParams.mode.toString(), ConfigParams.modes.activate.toString());

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public boolean sendDataMessage(ConfigParams.modes mode, String sendAs,
			String sendTo, String message) {
		try {
			UrlData urlData = new UrlData(this.getDataPostUrl(), 25000);

			Hashtable<String, String> htParams = getDataPostHashtable();

			htParams.put(ConfigParams.mode.toString(), mode.toString());
			htParams.put(ConfigParams.field1.toString(), message);
			htParams.put(ConfigParams.field2.toString(), sendTo);
			htParams.put(PhoneParams.sender.toString(), sendAs);

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				return true;
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public String getHelpContent() {
		try {
			UrlData urlData = new UrlData(getDataPostUrl());

			Hashtable<String, String> htParams = getDataPostHashtable();

			htParams.put(ConfigParams.mode.toString(),
					ConfigParams.modes.help.toString());

			UrlResponse response = urlData.postData(htParams);

			if (response.getMessage().toLowerCase().startsWith("error")) {
				return "error";
			} else if (response.getResponseType() == UrlResponseType.success) {
				return response.getMessage();
			} else {
				return "";
			}
		} catch (Exception e) {
			return "error";
		}
	}

	public boolean sendRegistrationIdToHost(String registrationId) {
		try {
			UrlData urlData = new UrlData(getDataPostUrl());

			Hashtable<String, String> htParams = getDataPostHashtable();
			
			htParams.put(ConfigParams.mode.toString(),
					ConfigParams.modes.c2dm.toString());

			htParams.put(ConfigParams.registrationid.toString(), registrationId);

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				return updateConfigFromHost();
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public boolean updateConfigFromHost() {
		try {
			this.rePopulate();

			UrlData urlData = new UrlData(getDataPostUrl());

			Hashtable<String, String> htParams = getDataPostHashtable();

			htParams.put(ConfigParams.mode.toString(),
					ConfigParams.modes.getconfig.toString());

			UrlResponse response = urlData.postData(htParams);
			if (response.getResponseType() == UrlResponseType.success) {
				return updateConfig(response.getMessage());
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public boolean sendConfigToHost(String urld, String failMessage,
			boolean battery, boolean signal, boolean counters, boolean gprs) {
		try {
			UrlData urlData = new UrlData(getDataPostUrl());

			Hashtable<String, String> htParams = getDataPostHashtable();
			
			htParams.put(ConfigParams.mode.toString(),
					ConfigParams.modes.setconfig.toString());

			htParams.put(ConfigParams.urld.toString(), urld);
			htParams.put(ConfigParams.fail_msg.toString(), failMessage);

			htParams.put(PhoneParams.batterystatus.toString(),
					String.valueOf(battery));
			htParams.put(PhoneParams.signalstatus.toString(),
					String.valueOf(signal));
			htParams.put(ConfigParams.counter.toString(),
					String.valueOf(counters));
			htParams.put(ConfigParams.gprs.toString(), String.valueOf(gprs));

			UrlResponse response = urlData.postData(htParams);

			if (response.getResponseType() == UrlResponseType.success) {
				return updateConfigFromHost();
			} else {
				return false;
			}
		} catch (Exception e) {
			return false;
		}
	}

	public void alert(String message) {
		AppHelper.alert(mContext, message);
	}

	/**
	 * Wakeup Lock
	 * 
	 * @param timeout
	 *            timeout in milliseconds
	 */
	public void wakeUp(long timeout) {
		AppHelper.wakeUp(mContext, timeout);
	}

	public final boolean isServiceRunning() {
		ActivityManager manager = (ActivityManager) mContext
				.getSystemService(Context.ACTIVITY_SERVICE);
		for (RunningServiceInfo srv : manager
				.getRunningServices(Integer.MAX_VALUE)) {
			if (srv.service.getClassName().equals(AppService.class.getName())) {
				return true;
			}
		}
		return false;
	}

	public void rePopulate() {
		super.rePopulate();
		
		this.mNotificationQueue.repopulate();
		getPhoneAttributesInstance().resetAllAttributes();
	}

	private boolean updateConfig(String rawConfig) {

		if (rawConfig.toLowerCase().startsWith("error")) {
			return false;
		}
		
		String[] allCfg = rawConfig.split(";");

		for (String keyValues : allCfg) {
			String[] keyValue = keyValues.replace("\n", "").split("=");
			
			try {
				setValue(keyValue[0], keyValue[1]);
			} catch (Exception e) {
				return false;
			}
		}

		try {
			setValue(PhoneParams.subid.toString(), getSubscriberId());
		} catch (Exception e) {
			return false;
		}

		try {
			setValue(PhoneParams.deviceid.toString(), getDeviceId());
		} catch (Exception e) {
			return false;
		}

		try {
			String currentDateTimeString = android.text.format.DateFormat
					.format("MM/dd/yyyy hh:mm aa", new Date()).toString();
			setConfigUpdateDateTime(currentDateTimeString);
		} catch (Exception e) {
			return false;
		}

		this.rePopulate();
		return true;
	}

	private PhoneAttributes getPhoneAttributesInstance() {
		if (mPhoneAttr == null)
			mPhoneAttr = new PhoneAttributes(mContext);
		return mPhoneAttr;
	}

	public ServiceStartStatus allGoodToRunService() {
		
		if (!isAppUpToDate())
			return ServiceStartStatus.NewUpdateAvailable;
		else if (isPaidFlag() && !isValidFlag())
			return ServiceStartStatus.SubscriptionExpired;
		else if (!isPaidFlag() && !isValidFlag())
			return ServiceStartStatus.DemoLimitation;
		else if (!isValidDataNetwork())
			return ServiceStartStatus.ConnectivityFailure;
		else if (is2GNetwork() && !isGprsFlag())
			return ServiceStartStatus.GprsNotAllowed;
		else if (isMissedServiceServiceFlag() && is2GNetwork())
			return ServiceStartStatus.Non2gNetworkRequired;
		else
			return ServiceStartStatus.Ok;
	}

	public void handleServiceResponse(ServiceStartStatus status) {
		switch (status) {
		case ConnectivityFailure:
			alert(mContext.getString(R.string.network_error));
			break;
		case IssueUpdatingConfigFile:
			alert(mContext.getString(R.string.config_download_error));
			break;
		case GprsNotAllowed:
			alert(mContext.getString(R.string.gprs_edge_not_allowed));
			break;
		case WifiRequired:
			alert(mContext.getString(R.string.wifi_required));
			break;
		case Non2gNetworkRequired:
			alert(mContext.getString(R.string.non2gnetworkrequired));
			break;
		case SubscriptionExpired:
			alert(mContext.getString(R.string.subscription_expired));
			break;
		case DemoLimitation:
			alert(mContext.getString(R.string.demo_limitation));
			break;
		case NewUpdateAvailable:
			checkUpdates();
			break;
		case Started:
		case Ok:
			break;
		}
	}

	public void checkUpdates() {
		if (isAppUpToDate()) {
			alert("Application is up-to-date");
		} else {
			questionForUpate();
		}
	}

	private final void questionForUpate() {
		AlertDialog.Builder builder = new AlertDialog.Builder(this.mContext);

		builder.setTitle("App Update")
				.setMessage("New version of app is available for download.")
				.setIcon(R.drawable.icon)
				.setPositiveButton("ok", new DialogInterface.OnClickListener() {
					@Override
					public void onClick(DialogInterface dialog, int which) {
						getUpdate();
					}
				})
				.setNegativeButton("Cancel",
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {

							}
						}).setCancelable(true);

		builder.show();
	}

	private final void getUpdate() {
		AppHelper.launchMarketUrl(mContext, mContext.getPackageName());
	}

	// /////////////////////////////////////////////////////////////////////

	public boolean isSubscribedFlag() {
		return getBooleanValue(ConfigParams.subscribed.toString());
	}

	public void setSubscribedFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.subscribed.toString(), value);
	}

	// *************************
	public boolean isGprsFlag() {
		return getBooleanValue(ConfigParams.gprs.toString());
	}

	public void setGprsFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.gprs.toString(), value);
	}

	// *************************
	public boolean isBatteryFlag() {
		return getBooleanValue(ConfigParams.battery.toString());
	}

	public void setBatteryFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.battery.toString(), value);
	}

	// *************************
	public boolean isSignalFlag() {
		return getBooleanValue(ConfigParams.signal.toString());
	}

	public void setSignalFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.signal.toString(), value);
	}

	// *************************
	public boolean isLocationFlag() {
		return getBooleanValue(ConfigParams.location.toString());
	}

	public void setLocationFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.location.toString(), value);
	}

	// *************************
	public boolean isCountersFlag() {
		return getBooleanValue(ConfigParams.counter.toString());
	}

	public void setCountersFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.counter.toString(), value);
	}

	// *************************
	public boolean isAdminConfigVisibleFlag() {
		return getBooleanValue(ConfigParams.config.toString());
	}

	public void setAdminConfigVisibilityFlag(boolean visible) throws Exception {
		setBooleanValue(ConfigParams.config.toString(), visible);
	}

	// *************************
	public boolean isActivatedFlag() {
		return getBooleanValue(ConfigParams.activated.toString());
	}

	public void setActivatedFlag(boolean visible) throws Exception {
		setBooleanValue(ConfigParams.activated.toString(), visible);
	}

	// *************************
	public boolean isAutoReplyFlag() {
		return getBooleanValue(PhoneParams.autoreply.toString());
	}

	public void setAutoReplyFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.autoreply.toString(), value);
	}

	// *************************
	public boolean isMarkAsReadFlag() {
		return getBooleanValue(PhoneParams.mark_as_read.toString());
	}

	public void setMarkAsReadFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.mark_as_read.toString(), value);
	}

	// *************************
	public int getSmsSuccessCount() {
		return getIntValue(PhoneParams.smssuccesscount.toString());
	}

	public void setSmsSuccessCount(int count) throws Exception {
		setIntValue(PhoneParams.smssuccesscount.toString(), count);
	}

	// *************************
	public int getSmsInvalidCount() {
		return getIntValue(PhoneParams.smsinvalidcount.toString());
	}

	public void setSmsInvalidCount(int count) throws Exception {
		setIntValue(PhoneParams.smsinvalidcount.toString(), count);
	}

	// *************************
	public int getSmsDroppedCount() {
		return getIntValue(PhoneParams.smsdroppedcount.toString());
	}

	public void setSmsDroppedCount(int count) throws Exception {
		setIntValue(PhoneParams.smsdroppedcount.toString(), count);
	}

	// *************************
	public int getSmsFailedCount() {
		return getIntValue(PhoneParams.smsfailedcount.toString());
	}

	public void setSmsFailedCount(int count) throws Exception {
		setIntValue(PhoneParams.smsfailedcount.toString(), count);
	}

	// *************************
	public int getCallSuccessCount() {
		return getIntValue(PhoneParams.callsuccesscount.toString());
	}

	public void setCallSuccessCount(int count) throws Exception {
		setIntValue(PhoneParams.callsuccesscount.toString(), count);
	}

	// *************************
	public int getCallFailedCount() {
		return getIntValue(PhoneParams.callfailedcount.toString());
	}

	public void setCallFailedCount(int count) throws Exception {
		setIntValue(PhoneParams.callfailedcount.toString(), count);
	}

	// *************************
	public String getSubscriberIdFromConfig() {
		return getValue(PhoneParams.subid.toString());
	}

	public void setSubscriberIdFromConfig(String value) throws Exception {
		setValue(PhoneParams.subid.toString(), value);
	}

	// *************************
	public String getDataPostUrl() {
		return getValue(ConfigParams.app_url.toString());
	}

	public void setDataPostUrl(String url) throws Exception {
		setValue(ConfigParams.app_url.toString(), url);
	}

	// *************************
	public String getDestination() {
		return getValue(ConfigParams.destination.toString());
	}

	public void setDestination(String value) throws Exception {
		setValue(ConfigParams.destination.toString(), value);
	}

	// *************************
	public String getVersion() {
		return getValue(ConfigParams.version.toString());
	}

	public void setVersion(String version) throws Exception {
		setValue(ConfigParams.version.toString(), version);
	}

	// *************************
	public int getFreeCount() {
		return getIntValue(ConfigParams.freecount.toString());
	}

	public void setFreeCount(int count) throws Exception {
		setIntValue(ConfigParams.freecount.toString(), count);
	}

	// *************************
	public int getAvailableFreeCount() {
		return getIntValue(ConfigParams.availablefreecounts.toString());
	}

	public void setAvailableFreeCount(int count) throws Exception {
		setIntValue(ConfigParams.availablefreecounts.toString(), count);
	}

	// *************************
	public boolean isPaidFlag() {
		return getBooleanValue(ConfigParams.paid.toString());
	}

	public void setPaidFlag(boolean value) throws Exception {
		setBooleanValue(ConfigParams.paid.toString(), value);
	}

	// *************************
	public boolean isServerNotificationFlag() {
		if (this.hasKey(PhoneParams.allow_server_notifications.toString()))
			return getBooleanValue(PhoneParams.allow_server_notifications
					.toString());
		else
			return true;
	}

	public void setServerNotificationFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.allow_server_notifications.toString(),
				value);
	}

	// *************************
	public boolean isAlphanumericSenderFlag() {
		return getBooleanValue(PhoneParams.allow_alphanumeric_sender.toString());
	}

	public void setAlphanumericSenderFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.allow_alphanumeric_sender.toString(), value);
	}
	// *************************
	public boolean isShortcodeSenderFlag() {
		return getBooleanValue(PhoneParams.allow_shortcode_sender.toString());
	}

	public void setShortcodeSenderFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.allow_shortcode_sender.toString(), value);
	}

	// *************************
	public boolean isWebSmsFlag() {
		return getBooleanValue(PhoneParams.allow_web_sms.toString());
	}

	public void setWebSmsFlag(boolean value) throws Exception {
		setBooleanValue(PhoneParams.allow_web_sms.toString(), value);
	}

	// *************************
	public String getScode() {
		return getValue(ConfigParams.scode.toString());
	}

	public void setScode(String value) throws Exception {
		setValue(ConfigParams.scode.toString(), value);
	}

	// *************************
	public int getValidity() {
		return getIntValue(ConfigParams.validity.toString());
	}

	public void setValidity(int value) throws Exception {
		setIntValue(ConfigParams.validity.toString(), value);
	}

	// *************************
	public String getFailReplyMsg() {
		return getValue(ConfigParams.fail_msg.toString());
	}

	public void setFailReplyMsg(String value) throws Exception {
		setValue(ConfigParams.fail_msg.toString(), value);
	}

	// *************************
	public String getHelpText() {
		return getValue(ConfigParams.helptext.toString());
	}

	public void setHelpText(String value) throws Exception {
		setValue(ConfigParams.helptext.toString(), value);
	}

	// *************************
	public String getConfigUpdateDateTime() {
		return getValue(ConfigParams.config_update_dttm.toString());
	}

	public void setConfigUpdateDateTime(String value) throws Exception {
		setValue(ConfigParams.config_update_dttm.toString(), value);
	}

	// *************************
	public boolean isSmsServiceFlag() {
		return getBooleanValue(ServiceTypes.sms_service.toString());
	}

	public void setSmsServiceFlag(boolean value) throws Exception {
		setBooleanValue(ServiceTypes.sms_service.toString(), value);
	}

	// *************************
	public boolean isMissedServiceServiceFlag() {
		return getBooleanValue(ServiceTypes.missedcall_service.toString());
	}

	public void setMissedServiceServiceFlag(boolean value) throws Exception {
		setBooleanValue(ServiceTypes.missedcall_service.toString(), value);
	}

	// *************************
	public String getRegistrationId() {
		return getValue(ConfigParams.registrationid.toString());
	}

	public void setRegistrationId(String value) throws Exception {
		setValue(ConfigParams.registrationid.toString(), value);
	}

	// *************************
	public String getLastNotification() {
		return getValue(ConfigParams.last_notification.toString());
	}

	public void setLastNotification(String value) throws Exception {
		setValue(ConfigParams.last_notification.toString(), value);
	}

	// *************************

	public boolean isValidFlag() {
		if (isPaidFlag()) {
			int v = getValidity();
			return (v > 0);
		} else {
			return (getAvailableFreeCount() > 0);
		}
	}

	public String getValidityStatus() {
		if (isPaidFlag()) {
			int v = getValidity();
			return (v > 0 ? String.valueOf(v) + " Days"
					: "Subscription Expired");
		} else {
			return String.valueOf(getAvailableFreeCount()) + " of "
					+ String.valueOf(getFreeCount());
		}
	}

	public String getEmail() {
		return getPhoneAttributesInstance().primaryEmail;
	}

	public String getDeviceId() {
		return getPhoneAttributesInstance().deviceId;
	}

	public String getSubscriberId() {
		return getPhoneAttributesInstance().subscriberId;
	}

	public String getLocation() {
		return getPhoneAttributesInstance().location;
	}

	public String getBatteryStatus() {
		return getPhoneAttributesInstance().batteryStatus;
	}

	public String getSignalStrength() {
		return getPhoneAttributesInstance().signalStrength;
	}

	public boolean isConnectedToNetwork() {
		return getPhoneAttributesInstance().isConnected;
	}

	public NetworkType getNetworkType() {
		return getPhoneAttributesInstance().networkType;
	}

	public boolean isWifiNetwork() {
		return (getPhoneAttributesInstance().networkType == NetworkType.WiFi);
	}

	public boolean is3GNetwork() {
		return (getPhoneAttributesInstance().networkType == NetworkType.HSDPA || getPhoneAttributesInstance().networkType == NetworkType.UMTS);
	}

	public boolean is2GNetwork() {
		return (getPhoneAttributesInstance().networkType == NetworkType.GPRS || getPhoneAttributesInstance().networkType == NetworkType.EDGE);
	}

	public boolean isGSMDevice() {
		return (getPhoneAttributesInstance().deviceType == DeviceType.GSM);
	}

	public boolean isCDMADevice() {
		return (getPhoneAttributesInstance().deviceType == DeviceType.CDMA);
	}

	public String getDeviceType() {
		return getPhoneAttributesInstance().deviceType.toString();
	}

	public boolean isValidDataNetwork() {
		boolean result = (mPhoneAttr.networkType != NetworkType.UnknownNotConnected);
		return result;
	}

	public void resetCounters() {

		try {
			setSmsSuccessCount(0);
		} catch (Exception e) {
		}

		try {
			setSmsInvalidCount(0);
		} catch (Exception e) {
		}

		try {
			setSmsDroppedCount(0);
		} catch (Exception e) {
		}

		try {
			setSmsFailedCount(0);
		} catch (Exception e) {
		}

		try {
			setCallSuccessCount(0);
		} catch (Exception e) {
		}

		try {
			setCallFailedCount(0);
		} catch (Exception e) {
		}
	}

	// *************************

	public void pushNotificationToQueue(String notification)
			throws FileNotFoundException, IOException {
		mNotificationQueue.push(notification);
	}

	public String getNotificationFromQueue(int index) {
		return mNotificationQueue.getValue(index);
	}

	public void clearNotificationQueue() throws FileNotFoundException,
			IOException {
		mNotificationQueue.clearQueue();
	}

	public int getNotificationQueueSize() {
		return mNotificationQueue.getSize();
	}

	// *************************

}
